#!/usr/bin/env node

// Capture the original working directory 
// Node.js scripts may have their working directory modified during execution,
// so we use multiple approaches to detect the true execution directory
let ORIGINAL_CWD = process.cwd(); // Default fallback

// Check if PWD was passed as an override (used by wrapper scripts)
if (process.env.CODEBASE_RAG_PWD) {
  ORIGINAL_CWD = process.env.CODEBASE_RAG_PWD;
} else {
  // Try standard environment variables that may contain the original directory
  if (process.env.PWD && process.env.PWD !== process.cwd()) {
    ORIGINAL_CWD = process.env.PWD;
  } else if (process.env.INIT_CWD) {
    ORIGINAL_CWD = process.env.INIT_CWD;
  }
}

// Suppress punycode deprecation warning before any imports
process.removeAllListeners('warning');
process.on('warning', (warning) => {
  if (warning.name === 'DeprecationWarning' && warning.message.includes('punycode')) {
    return; // Ignore punycode deprecation warnings
  }
  console.warn(warning.name + ': ' + warning.message);
});

import { CodeIndexOrchestrator } from './dist/services/orchestrator.js';
import { EmbedderFactory } from './dist/services/embedder-factory.js';
import { QdrantVectorStore } from './dist/vector-store/qdrant-client.js';
import { simpleCodeParser } from './dist/processors/simple-parser.js';
import { CacheManager } from './dist/services/cache-manager.js';
import { validateEmbedderConfig, getVectorStoreConfig } from './dist/config/env-config.js';
import { parseShellCommand, mapShellCommandToTool, convertArgsToToolParams, resolveDirectoryPath } from './dist/utils/shell-command-parser.js';

import { indexCodebaseTool } from './dist/tools/index-codebase.js';
import { searchCodeTool } from './dist/tools/search-code.js';
import { getIndexStatusTool } from './dist/tools/get-index-status.js';
import { clearIndexTool } from './dist/tools/clear-index.js';
import { initConfigTool } from './dist/tools/init-config.js';

import process from 'process';
import path from 'path';

/**
 * CLI wrapper for codebase-rag-mcp shell commands
 */
async function main() {
  try {
    const args = process.argv.slice(2);
    
    if (args.length === 0) {
      console.log(`
🔍 Codebase RAG MCP CLI

Usage: ./codebase-rag <command>

Commands:
  index <directory>                    - Index a codebase directory
  search "<query>"                     - Search indexed code
  search --max-results N "<query>"     - Search with custom result limit
  search --min-score N "<query>"       - Search with custom score threshold
  status                               - Get index status
  clear --confirm true                 - Clear index (requires confirmation)
  verify                               - Verify configuration

Examples:
  ./codebase-rag index /path/to/code
  ./codebase-rag search "function definition"
  ./codebase-rag search --max-results 5 "API endpoints"
  ./codebase-rag status
  ./codebase-rag verify
  ./codebase-rag clear --confirm true
`);
      process.exit(0);
    }

    // Join all arguments to form the command
    const command = args.join(' ');
    
    console.log(`🚀 Executing: ${command}`);
    
    // Parse the shell command
    const parsed = parseShellCommand(command);
    if (!parsed) {
      console.log("❌ Invalid command format");
      process.exit(1);
    }

    const toolName = mapShellCommandToTool(parsed.command);
    if (!toolName) {
      console.log(`❌ Unknown command: ${parsed.command}`);
      process.exit(1);
    }

    const toolParams = convertArgsToToolParams(toolName, parsed.args, ORIGINAL_CWD);

    // Handle commands that don't need orchestrator
    if (toolName === 'help') {
      console.log(`
🔍 Codebase RAG MCP CLI

Usage: codebase-rag <command>

Commands:
  init                                 - Initialize configuration files
  index <directory>                    - Index a codebase directory
  index --verbose <directory>          - Index with detailed progress output
  search "<query>"                     - Search indexed code
  search --max-results N "<query>"     - Search with custom result limit
  search --min-score N "<query>"       - Search with custom score threshold
  status                               - Get index status
  status --verbose                     - Get detailed index status with file breakdown
  clear --confirm true                 - Clear index (requires confirmation)
  verify                               - Verify configuration
  help, --help, -h                     - Show this help message

Examples:
  codebase-rag init                    # Initialize configuration files
  codebase-rag index .
  codebase-rag index --verbose /path/to/code  # Index with detailed output
  codebase-rag search "function definition"
  codebase-rag search --max-results 5 "API endpoints"
  codebase-rag status
  codebase-rag status --verbose           # Detailed status with file breakdown
  codebase-rag verify
  codebase-rag clear --confirm true

Relative Path Support:
  codebase-rag index .                 # Current directory
  codebase-rag index ./src             # Subdirectory
  codebase-rag index ../other          # Parent directory
  codebase-rag index /absolute/path    # Absolute path
`);
      process.exit(0);
    }

    if (toolName === 'init_config') {
      const result = await initConfigTool(toolParams);
      console.log('\n' + result);
      process.exit(0);
    }

    if (toolName === 'verify_configuration') {
      const embeddingValidation = validateEmbedderConfig();
      if (!embeddingValidation.valid) {
        console.log(`❌ **Embedder Configuration Error**\n\n${embeddingValidation.error}`);
        process.exit(1);
      }

      const embedder = EmbedderFactory.createEmbedder();
      const embeddingTest = await embedder.validateConfiguration();
      if (!embeddingTest.valid) {
        console.log(`❌ **Embedder Connection Error**\n\n${embeddingTest.error}`);
        process.exit(1);
      }

      const vectorStoreConfig = getVectorStoreConfig();
      const vectorDimensions = EmbedderFactory.getVectorDimensions();
      const vectorStore = new QdrantVectorStore(
        "/tmp/test",
        vectorStoreConfig.url,
        vectorDimensions,
        vectorStoreConfig.apiKey
      );
      await vectorStore.initialize();

      console.log(`✅ **Configuration Verified Successfully**\n\n**Embedder:** ${embedder.embedderInfo.name}\n**Vector Database:** Connected to ${vectorStoreConfig.url}\n**Vector Dimension (Code):** ${vectorDimensions.code}\n**Vector Dimension (Text):** ${vectorDimensions.text}\n\nYour system is ready for codebase indexing and search!`);
      process.exit(0);
    }

    // Create orchestrator for other commands
    const embedder = EmbedderFactory.createEmbedder();
    const vectorStoreConfig = getVectorStoreConfig();
    const vectorDimensions = EmbedderFactory.getVectorDimensions();
    
    // Use original working directory for cache and config
    const currentWorkingDir = ORIGINAL_CWD;
    // Target directory is already resolved by convertArgsToToolParams
    let targetDirectory = toolParams.directory || ORIGINAL_CWD;
    
    // Debug logging (remove in production)
    // console.log('🐛 DEBUG: ORIGINAL_CWD:', ORIGINAL_CWD);
    // console.log('🐛 DEBUG: currentWorkingDir:', currentWorkingDir);
    // console.log('🐛 DEBUG: toolParams.directory:', toolParams.directory);
    // console.log('🐛 DEBUG: targetDirectory:', targetDirectory);
    
    const vectorStore = new QdrantVectorStore(
      targetDirectory,
      vectorStoreConfig.url,
      vectorDimensions,
      vectorStoreConfig.apiKey
    );
    const cacheManager = new CacheManager(currentWorkingDir);
    const orchestrator = new CodeIndexOrchestrator(embedder, vectorStore, simpleCodeParser, cacheManager, currentWorkingDir);

    // Handle orchestrator errors gracefully (especially file watcher errors)
    orchestrator.on('error', (error) => {
      if (error.code === 'ENOSPC') {
        console.warn('⚠️  File watcher limit reached - continuing without real-time updates');
      } else {
        console.warn('⚠️  Warning:', error.message);
      }
    });

    // Execute the appropriate tool
    let result;
    switch (toolName) {
      case 'index_codebase':
        if (!toolParams.directory) {
          console.log("❌ **Missing Directory**\n\nUsage: `index <directory>`");
          process.exit(1);
        }
        try {
          result = await indexCodebaseTool(toolParams, orchestrator);
          // Give a moment for any async file watcher setup to complete
          await new Promise(resolve => setTimeout(resolve, 1000));
        } catch (error) {
          // If indexing failed, show the error
          console.error('❌ Indexing failed:', error.message);
          process.exit(1);
        }
        break;

      case 'search_code':
        if (!toolParams.query) {
          console.log("❌ **Missing Query**\n\nUsage: `search <query>`");
          process.exit(1);
        }
        result = await searchCodeTool(toolParams, orchestrator);
        break;

      case 'get_index_status':
        result = await getIndexStatusTool(toolParams, orchestrator);
        break;

      case 'clear_index':
        result = await clearIndexTool(toolParams, orchestrator);
        break;

      default:
        console.log(`❌ Unknown tool: ${toolName}`);
        process.exit(1);
    }

    console.log('\n' + result);
    
  } catch (error) {
    console.error('❌ Error:', error.message);
    process.exit(1);
  }
}

main();